#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2022/3/30 16:33
Desc: 新浪财经-债券-沪深可转债-实时行情数据和历史行情数据
http://vip.stock.finance.sina.com.cn/mkt/#hskzz_z
"""
import datetime
import json
import re

import pandas as pd
import requests
from bs4 import BeautifulSoup
from py_mini_racer import py_mini_racer
from tqdm import tqdm

from akshare.bond.cons import (
    zh_sina_bond_hs_cov_count_url,
    zh_sina_bond_hs_cov_payload,
    zh_sina_bond_hs_cov_url,
    zh_sina_bond_hs_cov_hist_url,
)
from akshare.stock.cons import hk_js_decode
from akshare.utils import demjson


def _get_zh_bond_hs_cov_page_count() -> int:
    """
    新浪财经-行情中心-债券-沪深可转债的总页数
    http://vip.stock.finance.sina.com.cn/mkt/#hskzz_z
    :return: 总页数
    :rtype: int
    """
    params = {
        "node": "hskzz_z",
    }
    r = requests.get(zh_sina_bond_hs_cov_count_url, params=params)
    page_count = int(re.findall(re.compile(r"\d+"), r.text)[0]) / 80
    if isinstance(page_count, int):
        return page_count
    else:
        return int(page_count) + 1


def bond_zh_hs_cov_spot() -> pd.DataFrame:
    """
    新浪财经-债券-沪深可转债的实时行情数据; 大量抓取容易封IP
    http://vip.stock.finance.sina.com.cn/mkt/#hskzz_z
    :return: 所有沪深可转债在当前时刻的实时行情数据
    :rtype: pandas.DataFrame
    """
    big_df = pd.DataFrame()
    page_count = _get_zh_bond_hs_cov_page_count()
    zh_sina_bond_hs_payload_copy = zh_sina_bond_hs_cov_payload.copy()
    for page in tqdm(range(1, page_count + 1), leave=False):
        zh_sina_bond_hs_payload_copy.update({"page": page})
        res = requests.get(zh_sina_bond_hs_cov_url, params=zh_sina_bond_hs_payload_copy)
        data_json = demjson.decode(res.text)
        big_df = big_df.append(pd.DataFrame(data_json), ignore_index=True)
    return big_df


def bond_zh_hs_cov_daily(symbol: str = "sh010107") -> pd.DataFrame:
    """
    新浪财经-债券-沪深可转债的历史行情数据, 大量抓取容易封 IP
    http://vip.stock.finance.sina.com.cn/mkt/#hskzz_z
    :param symbol: 沪深可转债代码; e.g., sh010107
    :type symbol: str
    :return: 指定沪深可转债代码的日 K 线数据
    :rtype: pandas.DataFrame
    """
    r = requests.get(
        zh_sina_bond_hs_cov_hist_url.format(
            symbol, datetime.datetime.now().strftime("%Y_%m_%d")
        )
    )
    js_code = py_mini_racer.MiniRacer()
    js_code.eval(hk_js_decode)
    dict_list = js_code.call(
        "d", r.text.split("=")[1].split(";")[0].replace('"', "")
    )  # 执行js解密代码
    data_df = pd.DataFrame(dict_list)
    data_df['date'] = pd.to_datetime(data_df["date"]).dt.date
    return data_df


def _code_id_map() -> dict:
    """
    东方财富-股票和市场代码
    http://quote.eastmoney.com/center/gridlist.html#hs_a_board
    :return: 股票和市场代码
    :rtype: dict
    """
    url = "http://80.push2.eastmoney.com/api/qt/clist/get"
    params = {
        "pn": "1",
        "pz": "5000",
        "po": "1",
        "np": "1",
        "ut": "bd1d9ddb04089700cf9c27f6f7426281",
        "fltt": "2",
        "invt": "2",
        "fid": "f3",
        "fs": "m:1 t:2,m:1 t:23",
        "fields": "f12",
        "_": "1623833739532",
    }
    r = requests.get(url, params=params)
    data_json = r.json()
    temp_df = pd.DataFrame(data_json["data"]["diff"])
    temp_df["market_id"] = 1
    temp_df.columns = ["sh_code", "sh_id"]
    code_id_dict = dict(zip(temp_df["sh_code"], temp_df["sh_id"]))
    params = {
        "pn": "1",
        "pz": "5000",
        "po": "1",
        "np": "1",
        "ut": "bd1d9ddb04089700cf9c27f6f7426281",
        "fltt": "2",
        "invt": "2",
        "fid": "f3",
        "fs": "m:0 t:6,m:0 t:80",
        "fields": "f12",
        "_": "1623833739532",
    }
    r = requests.get(url, params=params)
    data_json = r.json()
    temp_df_sz = pd.DataFrame(data_json["data"]["diff"])
    temp_df_sz["sz_id"] = 0
    code_id_dict.update(dict(zip(temp_df_sz["f12"], temp_df_sz["sz_id"])))
    return code_id_dict


def bond_zh_hs_cov_min(
        symbol: str = "sh113570",
        period: str = '15',
        adjust: str = '',
        start_date: str = "1979-09-01 09:32:00",
        end_date: str = "2222-01-01 09:32:00",
) -> pd.DataFrame:
    """
    东方财富网-可转债-分时行情
    https://quote.eastmoney.com/concept/sz128039.html
    :param symbol: 转债代码
    :type symbol: str
    :param period: choice of {'1', '5', '15', '30', '60'}
    :type period: str
    :param adjust: choice of {'', 'qfq', 'hfq'}
    :type adjust: str
    :param start_date: 开始日期
    :type start_date: str
    :param end_date: 结束日期
    :type end_date: str
    :return: 分时行情
    :rtype: pandas.DataFrame
    """
    market_type = {'sh': '1', 'sz': '0'}
    if period == '1':
        url = 'https://push2.eastmoney.com/api/qt/stock/trends2/get'
        params = {
            "fields1": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",
            "fields2": "f51,f52,f53,f54,f55,f56,f57,f58",
            "ut": "fa5fd1943c7b386f172d6893dbfba10b",
            "ndays": "5",
            "iscr": "0",
            'iscca': '0',
            "secid": f"{market_type[symbol[:2]]}.{symbol[2:]}",
            "_": "1623766962675",
        }
        r = requests.get(url, params=params)
        data_json = r.json()
        temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["trends"]])
        temp_df.columns = [
            "时间",
            "开盘",
            "收盘",
            "最高",
            "最低",
            "成交量",
            "成交额",
            "最新价",
        ]
        temp_df.index = pd.to_datetime(temp_df["时间"])
        temp_df = temp_df[start_date:end_date]
        temp_df.reset_index(drop=True, inplace=True)
        temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
        temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
        temp_df["最高"] = pd.to_numeric(temp_df["最高"])
        temp_df["最低"] = pd.to_numeric(temp_df["最低"])
        temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
        temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
        temp_df["最新价"] = pd.to_numeric(temp_df["最新价"])
        temp_df['时间'] = pd.to_datetime(temp_df['时间']).astype(str)  # 带日期时间
        return temp_df
    else:
        adjust_map = {
            '': '0',
            'qfq': '1',
            'hfq': '2',
        }
        url = 'https://push2his.eastmoney.com/api/qt/stock/kline/get'
        params = {
            'fields1': 'f1,f2,f3,f4,f5,f6',
            'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61',
            'ut': '7eea3edcaed734bea9cbfc24409ed989',
            'klt': period,
            'fqt': adjust_map[adjust],
            'secid': f"{market_type[symbol[:2]]}.{symbol[2:]}",
            'beg': '0',
            'end': '20500000',
            '_': '1630930917857',
        }
        r = requests.get(url, params=params)
        data_json = r.json()
        temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
        temp_df.columns = [
            "时间",
            "开盘",
            "收盘",
            "最高",
            "最低",
            "成交量",
            "成交额",
            "振幅",
            "涨跌幅",
            "涨跌额",
            "换手率",
        ]
        temp_df.index = pd.to_datetime(temp_df["时间"])
        temp_df = temp_df[start_date:end_date]
        temp_df.reset_index(drop=True, inplace=True)
        temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
        temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
        temp_df["最高"] = pd.to_numeric(temp_df["最高"])
        temp_df["最低"] = pd.to_numeric(temp_df["最低"])
        temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
        temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
        temp_df["振幅"] = pd.to_numeric(temp_df["振幅"])
        temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"])
        temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"])
        temp_df["换手率"] = pd.to_numeric(temp_df["换手率"])
        temp_df['时间'] = pd.to_datetime(temp_df['时间']).astype(str)  # 带日期时间
        temp_df = temp_df[[
            "时间",
            "开盘",
            "收盘",
            "最高",
            "最低",
            "涨跌幅",
            "涨跌额",
            "成交量",
            "成交额",
            "振幅",
            "换手率",
        ]]
        return temp_df


def bond_zh_cov() -> pd.DataFrame:
    """
    东方财富网-数据中心-新股数据-可转债数据
    http://data.eastmoney.com/kzz/default.html
    :return: 可转债数据
    :rtype: pandas.DataFrame
    """
    url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
    params = {
        'sortColumns': 'PUBLIC_START_DATE',
        'sortTypes': '-1',
        'pageSize': '500',
        'pageNumber': '1',
        'reportName': 'RPT_BOND_CB_LIST',
        'columns': 'ALL',
        'quoteColumns': 'f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f235~10~SECURITY_CODE~TRANSFER_PRICE,f236~10~SECURITY_CODE~TRANSFER_VALUE,f2~10~SECURITY_CODE~CURRENT_BOND_PRICE,f237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO,f239~10~SECURITY_CODE~RESALE_TRIG_PRICE,f240~10~SECURITY_CODE~REDEEM_TRIG_PRICE,f23~01~CONVERT_STOCK_CODE~PBV_RATIO',
        'source': 'WEB',
        'client': 'WEB',
    }
    r = requests.get(url, params=params)
    data_json = r.json()
    total_page = data_json["result"]["pages"]
    big_df = pd.DataFrame()
    for page in tqdm(range(1, total_page + 1), leave=False):
        params.update({"pageNumber": page})
        r = requests.get(url, params=params)
        data_json = r.json()
        temp_df = pd.DataFrame(data_json["result"]["data"])
        big_df = pd.concat([big_df, temp_df], ignore_index=True)

    big_df.columns = [
        "债券代码",
        "_",
        "_",
        "债券简称",
        "_",
        "上市时间",
        "正股代码",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "发行规模",
        "申购上限",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "申购代码",
        "_",
        "申购日期",
        "_",
        "_",
        "中签号发布日",
        "原股东配售-股权登记日",
        "正股简称",
        "原股东配售-每股配售额",
        "_",
        "中签率",
        "-",
        "_",
        "_",
        "_",
        "_",
        "_",
        "正股价",
        "转股价",
        "转股价值",
        "债现价",
        "转股溢价率",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
        "_",
    ]
    big_df = big_df[
        [
            "债券代码",
            "债券简称",
            "申购日期",
            "申购代码",
            "申购上限",
            "正股代码",
            "正股简称",
            "正股价",
            "转股价",
            "转股价值",
            "债现价",
            "转股溢价率",
            "原股东配售-股权登记日",
            "原股东配售-每股配售额",
            "发行规模",
            "中签号发布日",
            "中签率",
            "上市时间",
        ]
    ]
    big_df['申购日期'] = pd.to_datetime(big_df['申购日期'], errors='coerce').dt.date
    big_df['申购上限'] = pd.to_numeric(big_df['申购上限'], errors='coerce')
    big_df['正股价'] = pd.to_numeric(big_df['正股价'], errors='coerce')
    big_df['转股价'] = pd.to_numeric(big_df['转股价'], errors='coerce')
    big_df['转股价值'] = pd.to_numeric(big_df['转股价值'], errors='coerce')
    big_df['债现价'] = pd.to_numeric(big_df['债现价'], errors='coerce')
    big_df['转股溢价率'] = pd.to_numeric(big_df['转股溢价率'], errors='coerce')
    big_df['原股东配售-股权登记日'] = pd.to_datetime(big_df['原股东配售-股权登记日'], errors='coerce').dt.date
    big_df['原股东配售-每股配售额'] = pd.to_numeric(big_df['原股东配售-每股配售额'], errors='coerce')
    big_df['发行规模'] = pd.to_numeric(big_df['发行规模'], errors='coerce')
    big_df['中签号发布日'] = pd.to_datetime(big_df['中签号发布日'], errors='coerce').dt.date
    big_df['中签率'] = pd.to_numeric(big_df['中签率'], errors='coerce')
    big_df['上市时间'] = pd.to_datetime(big_df['上市时间'], errors='coerce').dt.date

    big_df['债现价'] = big_df['债现价'].fillna(100)
    return big_df


def bond_cov_comparison() -> pd.DataFrame:
    """
    东方财富网-行情中心-债券市场-可转债比价表
    http://quote.eastmoney.com/center/fullscreenlist.html#convertible_comparison
    :return: 可转债比价表数据
    :rtype: pandas.DataFrame
    """
    url = "http://16.push2.eastmoney.com/api/qt/clist/get"
    params = {
        "pn": "1",
        "pz": "5000",
        "po": "1",
        "np": "1",
        "ut": "bd1d9ddb04089700cf9c27f6f7426281",
        "fltt": "2",
        "invt": "2",
        "fid": "f243",
        "fs": "b:MK0354",
        "fields": "f1,f152,f2,f3,f12,f13,f14,f227,f228,f229,f230,f231,f232,f233,f234,f235,f236,f237,f238,f239,f240,f241,f242,f26,f243",
        "_": "1590386857527",
    }
    r = requests.get(url, params=params)
    text_data = r.text
    json_data = demjson.decode(text_data)
    temp_df = pd.DataFrame(json_data["data"]["diff"])
    temp_df.reset_index(inplace=True)
    temp_df['index'] = range(1, len(temp_df)+1)
    temp_df.columns = [
        "序号",
        "_",
        "转债最新价",
        "转债涨跌幅",
        "转债代码",
        "_",
        "转债名称",
        "上市日期",
        "_",
        "纯债价值",
        "_",
        "正股最新价",
        "正股涨跌幅",
        "_",
        "正股代码",
        "_",
        "正股名称",
        "转股价",
        "转股价值",
        "转股溢价率",
        "纯债溢价率",
        "回售触发价",
        "强赎触发价",
        "到期赎回价",
        "开始转股日",
        "申购日期",
    ]
    temp_df = temp_df[
        [
            "序号",
            "转债代码",
            "转债名称",
            "转债最新价",
            "转债涨跌幅",
            "正股代码",
            "正股名称",
            "正股最新价",
            "正股涨跌幅",
            "转股价",
            "转股价值",
            "转股溢价率",
            "纯债溢价率",
            "回售触发价",
            "强赎触发价",
            "到期赎回价",
            "纯债价值",
            "开始转股日",
            "上市日期",
            "申购日期",
        ]
    ]
    return temp_df


def bond_zh_cov_info(symbol: str = "123121") -> pd.DataFrame:
    """
    https://data.eastmoney.com/kzz/detail/123121.html
    东方财富网-数据中心-新股数据-可转债详情
    :param symbol: 可转债代码
    :type symbol: str
    :return: 可转债详情
    :rtype: pandas.DataFrame
    """
    if symbol == 'all':
        bond_zh_cov_temp = bond_zh_cov()
        code_list = bond_zh_cov_temp['债券代码'].tolist()
        big_df = pd.DataFrame()
        for item in tqdm(code_list, leave=False):
            url = f"http://data.eastmoney.com/kzz/detail/{item}.html"
            r = requests.get(url)
            soup = BeautifulSoup(r.text, "lxml")
            data_text = soup.find("script").string.strip()
            data_json = json.loads(re.findall("var info= (.*)", data_text)[0][:-1])
            temp_df = pd.json_normalize(data_json)
            big_df = big_df.append(temp_df, ignore_index=True)
        return big_df
    else:
        url = f"http://data.eastmoney.com/kzz/detail/{symbol}.html"
        r = requests.get(url)
        soup = BeautifulSoup(r.text, "lxml")
        data_text = soup.find("script").string.strip()
        data_json = json.loads(re.findall("var info= (.*)", data_text)[0][:-1])
        temp_df = pd.json_normalize(data_json)
        return temp_df


def bond_zh_cov_value_analysis(symbol: str = "123138") -> pd.DataFrame:
    """
    https://data.eastmoney.com/kzz/detail/113527.html
    东方财富网-数据中心-新股数据-可转债数据-价值分析-溢价率分析
    :return: 可转债价值分析
    :rtype: pandas.DataFrame
    """
    url = "https://datacenter-web.eastmoney.com/api/data/get"
    params = {
        'sty': 'ALL',
        'token': '894050c76af8597a853f5b408b759f5d',
        'st': 'date',
        'sr': '1',
        'source': 'WEB',
        'type': 'RPTA_WEB_KZZ_LS',
        'filter': f'(zcode="{symbol}")',
        'p': '1',
        'ps': '8000',
        '_': '1648629088839',
    }
    r = requests.get(url, params=params)
    data_json = r.json()
    temp_df = pd.DataFrame(data_json['result']['data'])
    temp_df.columns = [
        '日期',
        '-',
        '-',
        '转股价值',
        '纯债价值',
        '纯债溢价率',
        '转股溢价率',
        '收盘价',
        '-',
        '-',
        '-',
        '-',
    ]
    temp_df = temp_df[[
        '日期',
        '收盘价',
        '纯债价值',
        '转股价值',
        '纯债溢价率',
        '转股溢价率',
    ]]

    temp_df['日期'] = pd.to_datetime(temp_df['日期']).dt.date
    temp_df['收盘价'] = pd.to_numeric(temp_df['收盘价'])
    temp_df['纯债价值'] = pd.to_numeric(temp_df['纯债价值'])
    temp_df['转股价值'] = pd.to_numeric(temp_df['转股价值'])
    temp_df['纯债溢价率'] = pd.to_numeric(temp_df['纯债溢价率'])
    temp_df['转股溢价率'] = pd.to_numeric(temp_df['转股溢价率'])

    return temp_df


if __name__ == "__main__":
    bond_zh_hs_cov_min_df = bond_zh_hs_cov_min(symbol="sz123124", period='1', adjust='', start_date="1979-09-01 09:32:00", end_date="2222-01-01 09:32:00")
    print(bond_zh_hs_cov_min_df)

    bond_zh_hs_cov_daily_df = bond_zh_hs_cov_daily(symbol="sz123124")
    print(bond_zh_hs_cov_daily_df)

    bond_zh_hs_cov_spot_df = bond_zh_hs_cov_spot()
    print(bond_zh_hs_cov_spot_df)

    bond_zh_cov_df = bond_zh_cov()
    print(bond_zh_cov_df)

    bond_cov_comparison_df = bond_cov_comparison()
    print(bond_cov_comparison_df)

    bond_zh_cov_info_df = bond_zh_cov_info(symbol="all")
    print(bond_zh_cov_info_df)

    bond_zh_cov_value_analysis_df = bond_zh_cov_value_analysis(symbol="113527")
    print(bond_zh_cov_value_analysis_df)
